package com.qr.lunce;

import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;


/**
 * Lunce的使用：
 *
 */
public class StartLunce
{
    @Test
    public void cterateIndex(){
        //索引库存放在内存中，程序结束，这个索引库就没有了，不建议
//        RAMDirectory ramDirectory = new RAMDirectory();

        IndexWriter indexWriter = null;
        try {
                // 索引库放在磁盘上，这个open方法需要传入一个path,这个指定的是索引库保存的位置
                Directory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());
                /*
                * File file = new File("D:\\temp\\index");
                * Path path = file.toPath();
                * */
                // 创建写索引的对象
                indexWriter = new IndexWriter(directory,new IndexWriterConfig());

                //读取磁盘上的文件,传入的是一个文件夹，而不是一个文件，会将该目录下的子级目录也放放到数组当中
                File file = new File("D:\\temp");

                //得到文件列表
                File[] files = file.listFiles();

                //遍历文件列表，这里面会有目录
                for (File f : files) {
                    //得到每一个file对象
                    String name = f.getName();
                    //得到文件路径
                    String path = f.getPath();

                    System.out.println(name+"==============="+path);

                    //  FileNotFoundException: D:\temp\index (拒绝访问。)不能读取一个文件夹
                    //  String s = FileUtils.readFileToString(f, "utf-8");

                    //得到一个字符串。common-io中有一个FileUtils的方法，可以将文件读取转化为字符串
                    if (!f.isDirectory()){
                        //当file是一个目录的时候就报错，所以要排除目录
                        String s = FileUtils.readFileToString(f, "utf-8");
                        /**
                         * 排除目录
                         */
                        //这个方法不能读取文件夹，只能读取文件
                        long l = FileUtils.sizeOf(f);
                        System.out.println("文件的大小"+l);

                        //创建文档对象，将属性放到域当中
                        Document document = new Document();

                        /**
                         * 创建域对象：
                         *      域的名称
                         *      域的值
                         *      是否保存：YES保存
                         */
                        TextField fileName = new TextField("name", name, Field.Store.YES);
                        TextField filePath = new TextField("path", path, Field.Store.YES);
                        TextField fileContext = new TextField("s", s, Field.Store.YES);
                        TextField fileSize = new TextField("l", l+"", Field.Store.YES);

                        //将域对象添加到文档对象中
                        document.add(fileName);
                        document.add(filePath);
                        document.add(fileContext);
                        document.add(fileSize);

                        //将文档对象写入到索引库
                        indexWriter.addDocument(document);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (indexWriter!=null) {
                    try{
                        indexWriter.close();
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
    }


    /**
     * 查询索引库,单元测试必须是public来修饰的
     */
    @Test
    public void searchIndex(){

        try {
            //创建Directory对象指定索引库的位置
            FSDirectory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());

            //创建读取索引的对象
            IndexReader indexReader = DirectoryReader.open(directory);

            //创建indexSearch对象，传入读取索引的对象
            IndexSearcher indexSearcher = new IndexSearcher(indexReader);

            //创建term对象，term就是每个关键词都封装成了term对象，包括关键词所在的域，关键词本身
            /**
             * 上面添加索引的时候，创建了四个域
             *      name path s l
             */
            Term term = new Term("s", "string");

            //创建查询对象
            Query termQuery = new TermQuery(term);

            //查询
            TopDocs topDocs = indexSearcher.search(termQuery, 10);
            //查询的时候，命中了多少条
            System.out.println(topDocs.totalHits);

            ScoreDoc[] scoreDocs = topDocs.scoreDocs;

            //文档中的内容
            for (ScoreDoc scoreDoc : scoreDocs) {

                //文档id
                int docId = scoreDoc.doc;

                //获取该文档对象
                Document document = indexSearcher.doc(docId);

                //获取文档中的属性
                System.out.println(document.getField("name"));
                System.out.println(document.getField("path"));
                System.out.println(document.getField("s"));
                System.out.println(document.getField("l"));

            }

        }catch (Exception e){

            e.printStackTrace();

        }finally {



        }
    }

    /**
     * 测试分析器
     */
    @Test
    public void testAnalyer()throws Exception{
        //创建一个标准分析器
        Analyzer analyzer = new StandardAnalyzer();

        /**
         * 参数1：域名
         * 参数2: 要分析的文本的内容
         */
//        TokenStream tokenStream = analyzer.tokenStream("test", "I am fine thanks what are you doing");

        //英文单词能单独，汉字也是一个汉字一个位置进行了分词
        TokenStream tokenStream = analyzer.tokenStream("test", "标准分析器分析中文");

        //添加引用，可以获得每个关键词的引用
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);

        //将指针调整到列表的头部，便于从开始遍历拿数据
        tokenStream.reset();

        //遍历关键词列表，有引用后会根据引用一个一个往下面去拿
        while (tokenStream.incrementToken()){

            String s = charTermAttribute.toString();
            System.out.println(s);
        }
        tokenStream.close();
    }


    /**
     * ik分词器的使用，maven中的包不能使用，还是需要自己导入ik这个包
     * 拓展词典：hotword.dic中进行添加
     * 停用词典：stopword.dic中进行添加
     */
    @Test
    public void testIKAnalyer()throws Exception{
        //创建一个标准分析器
        Analyzer analyzer = new IKAnalyzer();

        //ik分词可以对中文进行分词
        TokenStream tokenStream = analyzer.tokenStream("test", "标准分析器分析中文,老色批");

        //添加引用，可以获得每个关键词的引用
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);

        //将指针调整到列表的头部，便于从开始遍历拿数据
        tokenStream.reset();

        //遍历关键词列表，有引用后会根据引用一个一个往下面去拿
        while (tokenStream.incrementToken()){

            String s = charTermAttribute.toString();
            System.out.println(s);
        }
        tokenStream.close();
    }


    /**
     * 使用ik进行分词创建索引
     */
    @Test
    public void cterateIKIndex(){
        IndexWriter indexWriter = null;
        try {
            Directory directory = FSDirectory.open(new File("D:\\temp\\index").toPath());
            // IK创建
            indexWriter = new IndexWriter(directory,new IndexWriterConfig(new IKAnalyzer()));

            File file = new File("D:\\temp");

            File[] files = file.listFiles();

            for (File f : files) {
                String name = f.getName();
                String path = f.getPath();
                System.out.println(name+"==============="+path);
                if (!f.isDirectory()){
                    String s = FileUtils.readFileToString(f, "utf-8");
                    long l = FileUtils.sizeOf(f);
                    Document document = new Document();
                    TextField fileName = new TextField("name", name, Field.Store.YES);
                    TextField filePath = new TextField("path", path, Field.Store.YES);
                    TextField fileContext = new TextField("s", s, Field.Store.YES);
                    TextField fileSize = new TextField("l", l+"", Field.Store.YES);
                    document.add(fileName);
                    document.add(filePath);
                    document.add(fileContext);
                    document.add(fileSize);
                    indexWriter.addDocument(document);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (indexWriter!=null) {
                try{
                    indexWriter.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void isDre(){

        /**
         * 判断一个位置是否是一个目录
         */
        File file = new File("D:\\temp\\index");
        boolean directory = file.isDirectory();
        //true
        System.out.println(directory);

    }

}
